<template>
  <div v-show="playList.length" class="player">
    <transition
      name="normal"
      @enter="enter"
      @afterEnter="afterEnter"
      @leave="leave"
      @afterLeave="afterLeave"
    >
      <div v-show="fullScreen" class="normal-player">
        <div class="background">
          <img :src="currentSong.pic" alt="" />
        </div>
        <div class="top">
          <div class="back" @click="back">
            <i class="iconfont purple-down"></i>
          </div>
          <div class="title">{{ currentSong.name }}</div>
          <div class="subtitle">{{ currentSong.singer }}</div>
        </div>
        <div
          class="middle"
          @touchstart.prevent="onTouchStart"
          @touchmove="onTouchMove"
          @touchend="onTouchEnd"
        >
          <div :style="middleLeftStyle" class="middle-l">
            <div class="cd">
              <div ref="cdWrapper" class="img-wrapper">
                <img ref="imgRef" :src="currentSong.pic" alt="" />
              </div>
            </div>
            <div class="current-lyric">{{ currentLyric }}</div>
          </div>
          <div :style="middleRightStyle" class="middle-r">
            <Scroll ref="scroll">
              <div ref="lyricWrapper" class="lyric-wrapper">
                <div
                  :class="{ active: index === currentLine }"
                  v-for="(item, index) in lyricArray"
                  :key="item[0]"
                >
                  {{ item[1] }}
                </div>
              </div>
            </Scroll>
          </div>
        </div>
        <div class="bottom">
          <div class="dot-wrapper">
            <span class="dot" :class="{ active: currentView === 'cd' }"></span>
            <span
              class="dot"
              :class="{ active: currentView === 'lyric' }"
            ></span>
          </div>
          <Progress
            :progress="progress"
            :current-time="currentTime"
            :duration="currentSong.duration"
            @progress-changing="progressChanging"
            @progress-changed="progressChanged"
          ></Progress>
          <div class="operator">
            <div class="icon-left">
              <i class="iconfont" :class="modeIcon" @click="changeMode"></i>
            </div>
            <div class="icon-left" :class="disableClass">
              <i class="iconfont purple-prev-next" @click="prev"></i>
            </div>
            <div class="icon-center" :class="disableClass">
              <i
                class="iconfont purple-play2"
                :class="[playing ? 'purple-pause2' : 'purple-play2']"
                @click="togglePlay"
              ></i>
            </div>
            <div class="icon-right rotate" :class="disableClass">
              <i class="iconfont purple-prev-next" @click="next"></i>
            </div>
            <div class="icon-right">
              <i class="iconfont" :class="getFavouriteIcon" @click="toggle"></i>
            </div>
          </div>
        </div>
      </div>
    </transition>
    <MiniPlayer
      v-show="!fullScreen"
      :toggle-play="togglePlay"
      :next="next"
      :play-progress="progress"
    ></MiniPlayer>
    <audio
      ref="audioRef"
      @pause="pause"
      @canplay="ready"
      @error="error"
      @timeupdate="updateTime"
      @ended="end"
    ></audio>
  </div>
</template>

<script>
import { useStore } from 'vuex'
import { computed, watch, ref } from 'vue'
import { PLAY_MODE } from '@/assets/js/constant'
import useFavourite from './useFavourite'
import Progress from '@/components/Player/Progress'
import useCd from '@/components/Player/useCd'
import useLyric from '@/components/Player/useLyric'
import Scroll from '@/components/Base/Scroll/Scroll'
import useInteractive from './useInteractive'
import MiniPlayer from './MiniPlayer'
import useAnimation from './useAnimation'
export default {
  name: 'Player',
  components: {
    Progress,
    Scroll,
    MiniPlayer
  },
  setup() {
    const audioRef = ref(null)
    const songReady = ref(false)
    const { state, getters, commit, dispatch } = useStore()
    const { getFavouriteIcon, toggle } = useFavourite()
    const currentTime = ref(0)
    const isProgressChanging = ref(false)
    const { imgRef } = useCd()
    const {
      lyricArray,
      findCurrentLine,
      currentLine,
      scroll,
      currentLyric
    } = useLyric()
    const {
      middleLeftStyle,
      middleRightStyle,
      onTouchStart,
      onTouchMove,
      onTouchEnd,
      currentView
    } = useInteractive()
    const { enter, afterEnter, leave, afterLeave, cdWrapper } = useAnimation()

    const fullScreen = computed(() => {
      return state.play.fullScreen
    })
    const currentSong = computed(() => {
      return getters['play/currentSong']
    })
    const playing = computed(() => {
      return state.play.playing
    })
    const currentIndex = computed(() => {
      return state.play.currentIndex
    })
    const playList = computed(() => {
      return state.play.playList
    })
    const disableClass = computed(() => {
      return songReady.value ? '' : 'disable'
    })
    const playMode = computed(() => {
      return state.play.playMode
    })
    const modeIcon = computed(() => {
      switch (playMode.value) {
        case PLAY_MODE.SEQUENCE:
          return 'purple-loop'
        case PLAY_MODE.LOOP:
          return 'purple-loop-one'
        case PLAY_MODE.RANDOM:
          return 'purple-random'
        default:
          return 'purple-loop'
      }
    })
    const progress = computed(() => {
      return currentTime.value / currentSong.value.duration
    })

    watch(currentSong, newSong => {
      currentTime.value = 0
      if (newSong.id && newSong.url) {
        songReady.value = false
        const dom = audioRef.value
        dom.src = newSong.url
        dom.play()
      }
    })

    watch(playing, newPlaying => {
      if (!songReady.value) return
      const dom = audioRef.value
      newPlaying ? dom.play() : dom.pause()
    })

    function back() {
      commit('play/setFullScreen', false)
    }

    function togglePlay() {
      if (!songReady.value) return
      commit('play/setPlayingState', !state.play.playing)
    }

    function pause() {
      commit('play/setPlayingState', false)
    }

    function prev() {
      let newIndex = currentIndex.value - 1
      const length = playList.value.length
      if (!length || !songReady.value) return
      if (length === 1) {
        loop()
      } else {
        if (newIndex === -1) {
          newIndex = length - 1
        }
        commit('play/setCurrentIndex', newIndex)
        if (!playing.value) {
          commit('play/setPlayingState', true)
        }
      }
    }

    function next() {
      let newIndex = currentIndex.value + 1
      const length = playList.value.length
      if (!length || !songReady.value) return
      if (length === 1) {
        loop()
      } else {
        if (newIndex === length) {
          newIndex = 0
        }
        commit('play/setCurrentIndex', newIndex)
        if (!playing.value) {
          commit('play/setPlayingState', true)
        }
      }
    }

    function loop() {
      const dom = audioRef.value
      dom.currentTime = 0
      dom.play()
      if (!playing.value) {
        commit('play/setPlayingState', true)
      }
    }

    function ready() {
      if (!songReady.value) {
        songReady.value = true
      }
    }

    function error() {
      songReady.value = true
    }

    function changeMode() {
      const willMode = (playMode.value + 1) % 3
      dispatch('play/changeMode', willMode)
    }

    function updateTime(e) {
      if (isProgressChanging.value) return
      currentTime.value = e.target.currentTime
      findCurrentLine(e.target.currentTime)
    }

    function progressChanging(newProgress) {
      isProgressChanging.value = true
      currentTime.value = newProgress * currentSong.value.duration
    }

    function progressChanged(newProgress) {
      isProgressChanging.value = false
      audioRef.value.currentTime = currentTime.value =
        newProgress * currentSong.value.duration
      if (!playing.value) {
        togglePlay()
      }
    }

    function end() {
      if (playMode.value === PLAY_MODE.LOOP) {
        loop()
      } else {
        next()
      }
    }

    return {
      fullScreen,
      currentSong,
      audioRef,
      back,
      playing,
      playList,
      togglePlay,
      pause,
      prev,
      next,
      ready,
      disableClass,
      error,
      modeIcon,
      changeMode,
      getFavouriteIcon,
      toggle,
      progress,
      currentTime,
      updateTime,
      progressChanging,
      progressChanged,
      end,
      imgRef,
      lyricArray,
      currentLine,
      scroll,
      currentLyric,
      middleLeftStyle,
      middleRightStyle,
      onTouchStart,
      onTouchMove,
      onTouchEnd,
      currentView,
      enter,
      afterEnter,
      leave,
      afterLeave,
      cdWrapper
    }
  }
}
</script>

<style lang="scss" scoped>
.player {
  .normal-player {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 50;
    background-color: #222;
    .background {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      opacity: 0.6;
      filter: blur(20px);
      > img {
        width: 100%;
        height: 100%;
      }
    }
    .top {
      position: relative;
      margin-bottom: 25px;
      .back {
        position: absolute;
        left: 6px;
        padding: 10px;
        > i {
          font-size: 24px;
          font-weight: bold;
          color: $color-button-little;
        }
      }
      .title {
        text-align: center;
        line-height: 40px;
        font-size: 18px;
        color: #fff;
      }
      .subtitle {
        text-align: center;
        font-size: 14px;
        color: #fff;
      }
    }
    .middle {
      position: fixed;
      top: 80px;
      bottom: 170px;
      white-space: nowrap;
      width: 100%;
      .middle-l {
        display: inline-block;
        vertical-align: top;
        width: 100%;
        .cd {
          position: relative;
          width: 100%;
          height: 0;
          padding-top: 80%;
          .img-wrapper {
            position: absolute;
            top: 0;
            left: 50%;
            transform: translate3d(-50%, 0, 0);
            width: 80%;
            height: 100%;
            > img {
              width: 100%;
              height: 100%;
              border-radius: 50%;
              border: 10px solid rgba(255, 255, 255, 0.1);
              animation: rotate 20s linear infinite;
            }
          }
        }
        .current-lyric {
          text-align: center;
          margin: 30px auto 0 auto;
          font-size: 14px;
          color: rgba(255, 255, 255, 0.5);
        }
      }
      .middle-r {
        display: inline-block;
        vertical-align: top;
        width: 100%;
        height: 100%;
        overflow: hidden;
        > div {
          text-align: center;
          line-height: 32px;
          font-size: 14px;
          color: rgba(255, 255, 255, 0.5);
          .active {
            color: #fff;
          }
        }
      }
    }
    .bottom {
      position: absolute;
      width: 100%;
      left: 0;
      bottom: 50px;
      .dot-wrapper {
        text-align: center;
        > .dot {
          display: inline-block;
          vertical-align: top;
          width: 8px;
          height: 8px;
          border-radius: 50%;
          background-color: rgba(255, 255, 255, 0.5);
          margin: 0 5px;
          &.active {
            width: 20px;
            border-radius: 5px;
            background-color: rgba(255, 255, 255, 0.8);
          }
        }
      }
      .operator {
        display: flex;
        align-items: center;
        > div {
          flex: 1;
          > i {
            font-size: 30px;
            color: $color-list-title;
          }
          &.icon-left {
            text-align: right;
          }
          &.icon-center {
            text-align: center;
            padding: 0 25px;
            > i {
              font-size: 45px;
            }
          }
          &.icon-right {
            text-align: left;
          }
          &.disable {
            > i {
              color: rgba(242, 105, 430, 0.4);
            }
          }
        }
        .rotate {
          text-align: right !important;
          transform: rotate(180deg);
        }
      }
    }
  }
  .normal-enter-active,
  .normal-leave-active {
    transition: all 0.6s linear;
    .top {
      transition: all 0.6s linear;
    }
    .bottom {
      transition: all 0.6s linear;
    }
  }

  .normal-enter-from,
  .normal-leave-to {
    opacity: 0;
    .top {
      transform: translate3d(0, -50px, 0);
    }
    .bottom {
      transform: translate3d(0, 50px, 0);
    }
  }
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>
